package service

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fx_swift_forex/api"
	"fx_swift_forex/internal/model"
	"fx_swift_forex/pkg/code"
	"fx_swift_forex/pkg/global"
	"fx_swift_forex/pkg/httputils"
	"fx_swift_forex/pkg/internalerrors"
	"fx_swift_forex/pkg/logger"
	"github.com/gogf/gf/v2/frame/g"
	"io"
	"net/http"
)

// 调用登陆接口，获取CC银行临时token
func GetCurrencyCloudToken(ctx context.Context) (string, error) {
	var (
		url  = global.ViperObj.GetString("forex.baseUrl") + "/v2/authenticate/api"
		err  error
		resp *http.Response
		body []byte
		obj  api.CurrencyCloudLoginRes
	)
	//组装请求header参数
	headers := map[string]string{
		"Content-Type": "application/json",
	}

	//组装请求body参数
	reqObj := &api.CurrencyCloudLoginReq{
		LoginId: global.ViperObj.GetString("forex.loginId"),
		ApiKey:  global.ViperObj.GetString("forex.apiKey"),
	}
	body, err = json.Marshal(&reqObj)
	//请求cc银行接口获取token
	resp, _ = httputils.HTTPPost(url, headers, body)
	if resp.StatusCode != 200 {
		respData := &api.RespData{}
		body, err = io.ReadAll(resp.Body)
		json.Unmarshal(body, &respData)
		jsonStr, _ := json.Marshal(respData.ErrMessages)
		logger.SugarLogger.Error(string(jsonStr))
		return "", errors.New(string(jsonStr))
	}

	body, err = io.ReadAll(resp.Body)
	err = json.Unmarshal(body, &obj)
	if err != nil {
		logger.SugarLogger.Errorf("json 读取报错：%w", err)
		return "", err
	}
	//token写入redis，并设置过期时间
	if err = g.Redis().SetEX(ctx, global.ViperObj.GetString("forex.loginId"), obj.AuthToken, global.ViperObj.GetInt64("token.forex_expired_time")); err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	return obj.AuthToken, nil
}

// 调用cc银行登出接口注销token
func PostCurCloudLogout(ctx context.Context, authToken string) error {
	var (
		url        = global.ViperObj.GetString("forex.baseUrl") + "/v2/authenticate/close_session"
		resp       *http.Response
		err        error
		resultNums int64
	)

	//组装请求header参数
	headers := map[string]string{
		"X-Auth-Token": authToken,
	}

	resp, _ = httputils.HTTPPost(url, headers, nil)
	if resp.StatusCode != 200 {
		logger.SugarLogger.Error(resp.Status)
		return errors.New("Token注销失败")
	}
	//清除redis中的cc银行token
	resultNums, err = g.Redis().Del(ctx, global.ViperObj.GetString("forex.loginId"))
	if err != nil || resultNums == 0 {
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	return err
}

func GetRequestToCC(ctx context.Context, url string, params map[string]string) ([]byte, error) {
	var (
		resp       *http.Response
		redisToken string
		err        error
		body       []byte
	)
	redisToken, err = GetCCTokenToRedis(ctx)
	headers := map[string]string{
		"Content-Type": "application/json",
		"X-Auth-Token": redisToken,
	}
	resp, err = httputils.HttpGet(url, headers, params)
	if resp.StatusCode != 200 {
		respData := &api.RespData{}
		body, err = io.ReadAll(resp.Body)
		json.Unmarshal(body, &respData)
		jsonStr, _ := json.Marshal(respData.ErrMessages)
		return nil, errors.New(string(jsonStr))
	}
	if err != nil {
		return nil, err
	}
	body, err = io.ReadAll(resp.Body)
	return body, err
}

func PostRequestToCC(ctx context.Context, url, contentType string, writer *bytes.Buffer) ([]byte, error) {
	var (
		resp       *http.Response
		redisToken string
		err        error
		body       []byte
	)
	redisToken, err = GetCCTokenToRedis(ctx)
	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	headers := map[string]string{
		"Content-Type": contentType,
		"X-Auth-Token": redisToken,
	}
	//组装请求body参数
	resp, err = httputils.HTTPPostBuffer(url, headers, writer)
	if resp.StatusCode != 200 {
		respData := &api.RespData{}
		body, err = io.ReadAll(resp.Body)
		json.Unmarshal(body, &respData)
		jsonStr, _ := json.Marshal(respData.ErrMessages)
		return nil, errors.New(string(jsonStr))
	}
	if err != nil {
		return nil, err
	}
	body, err = io.ReadAll(resp.Body)
	return body, err
}

// 获取comply平台accessToken
func GetComplyToken(ctx context.Context) (string, error) {
	var (
		url  = global.ViperObj.GetString("comply.baseUrl") + "/v1/token"
		err  error
		resp *http.Response
		body []byte
		obj  api.ComplyAuthRes
	)
	//组装请求header参数
	headers := map[string]string{
		"content-type": "application/json",
		"accept":       "*/*",
	}

	//组装请求body参数
	reqObj := &api.ComplyAuthReq{
		UserName: global.ViperObj.GetString("comply.userName"),
		PassWord: global.ViperObj.GetString("comply.passWord"),
		Realm:    global.ViperObj.GetString("comply.realm"),
	}
	body, err = json.Marshal(&reqObj)
	//请求cc银行接口获取token
	resp, _ = httputils.HTTPPost(url, headers, body)
	if resp.StatusCode != 200 {
		return "", errors.New("获取accessToken失败")
	}

	body, err = io.ReadAll(resp.Body)
	err = json.Unmarshal(body, &obj)
	if err != nil {
		logger.SugarLogger.Errorf("json 读取报错：%w", err)
		return "", err
	}
	//token写入redis，并设置过期时间
	if err = g.Redis().SetEX(ctx, global.ViperObj.GetString("comply.tokenFlag")+global.ViperObj.GetString("comply.userName"), "Bearer "+obj.AccessToken, global.ViperObj.GetInt64("token.comply_expired_time")); err != nil {
		return "", internalerrors.New(code.ErrUnknown, err.Error())
	}
	return obj.AccessToken, nil
}

// 请求comply创建kyc记录
func DoPostCompanyComply(ctx context.Context, req *ComplyCompanyOnboardingReq) (string, error) {
	var (
		url         = global.ViperObj.GetString("comply.baseUrl") + "/v1/workflows/create-and-screen"
		err         error
		resp        *http.Response
		body        []byte
		obj         api.ComplyOnboardingRes
		accessToken string
	)
	//获取token
	accessToken, err = GetComplyTokenToRedis(ctx)
	if err != nil {
		logger.SugarLogger.Errorf("读取token失败：%w", err)
		return "", internalerrors.New(code.ErrUnknown, "读取token失败")
	}
	//组装请求header参数
	headers := map[string]string{
		"content-type":  "application/json",
		"accept":        "application/json",
		"authorization": accessToken,
	}

	body, err = json.Marshal(&req)
	resp, _ = httputils.HTTPPost(url, headers, body)
	if resp.StatusCode != 200 {
		respData := &api.ComplyRespData{}
		body, err = io.ReadAll(resp.Body)
		json.Unmarshal(body, &respData)
		jsonStr, _ := json.Marshal(respData.Message)
		logger.SugarLogger.Errorf("kyc接口请求返回报错：%w", string(jsonStr))
		return "", errors.New(string(jsonStr))
	}

	body, err = io.ReadAll(resp.Body)
	err = json.Unmarshal(body, &obj)
	if err != nil {
		logger.SugarLogger.Errorf("ComplyOnboardingRes读取报错：%w", err)
		return "", err
	}
	return obj.WorkflowInstanceIdentifier, nil
}

// 请求comply创建kyc记录
func DoPostPersonComply(ctx context.Context, req *model.ComplyPersonOnboardingReq) (string, error) {
	var (
		url         = global.ViperObj.GetString("comply.baseUrl") + "/v1/workflows/create-and-screen"
		err         error
		resp        *http.Response
		body        []byte
		obj         api.ComplyOnboardingRes
		accessToken string
	)
	//获取token
	accessToken, err = GetComplyTokenToRedis(ctx)
	if err != nil {
		logger.SugarLogger.Errorf("读取token失败：%w", err)
		return "", internalerrors.New(code.ErrUnknown, "读取token失败")
	}
	//组装请求header参数
	headers := map[string]string{
		"content-type":  "application/json",
		"accept":        "application/json",
		"authorization": accessToken,
	}

	body, err = json.Marshal(&req)
	resp, _ = httputils.HTTPPost(url, headers, body)
	if resp.StatusCode != 200 {
		respData := &api.ComplyRespData{}
		body, err = io.ReadAll(resp.Body)
		json.Unmarshal(body, &respData)
		jsonStr, _ := json.Marshal(respData.Message)
		logger.SugarLogger.Errorf("kyc接口请求返回报错：%w", string(jsonStr))
		return "", errors.New(string(jsonStr))
	}

	body, err = io.ReadAll(resp.Body)
	err = json.Unmarshal(body, &obj)
	if err != nil {
		logger.SugarLogger.Errorf("ComplyOnboardingRes读取报错：%w", err)
		return "", err
	}
	return obj.WorkflowInstanceIdentifier, nil
}
